//
//  WmcPresentAnimation.swift
//  YPWatermarkCamera
//
//  Created by 赵新 on 2022/3/3.
//

import UIKit
import YPBedrock

extension WmcPresentVC {
    /// 动画对象
    class Animation: NSObject {
        /// 状态
        var state: State = .present

        /// 出现/消失时候的动画时间
        var animationDuration: Numerical<CGFloat> = .init(all: Wmc_animationDuration)

        /// 动画延时
        var delay: Numerical<CGFloat> = .init(all: 0)

        /// 弹性系数 0-1 越小弹性效果越明显
        var usingSpringWithDamping: Numerical<CGFloat> = .init(present: 0.7, dismiss: 2)

        /// 初始速度系数，0-100 越大初始速度越快
        var initialSpringVelocity: Numerical<CGFloat> = .init(all: 1)

        /// 动画曲线类型
        var animationOptions: Numerical<UIView.AnimationOptions> = .init(present: .curveEaseOut, dismiss: .curveEaseIn)
    }
}

/// 动画对象
typealias WmcPresentAnimation = WmcPresentVC.Animation

extension WmcPresentAnimation {
    /// 状态
    enum State {
        case present, dismiss
    }

    /// 数值，用于处理出现和消失
    struct Numerical<T> {
        // Lifecycle

        /// 统一实例化
        init(all: T) {
            self.present = all
            self.dismiss = all
        }

        init(present: T, dismiss: T) {
            self.present = present
            self.dismiss = dismiss
        }

        // Internal

        var present: T
        var dismiss: T

        func value(_ state: State) -> T {
            switch state {
            case .present: return present
            case .dismiss: return dismiss
            }
        }
    }
}

// MARK: - 动画实现

extension WmcPresentAnimation {
    /// alert动画
    func alertAnimtion(_ state: State,
                       alertConfig: WmcPresentVC.Style.AlertConfig,
                       superView: UIView,
                       contentView: UIView,
                       config: WmcPresentVC.Config,
                       completion: @escaping YPBlock.Empty)
    {
        switch state {
        case .present:
            superView.addSubview(contentView)
            contentView.snp.remakeConstraints { make in
                config.contentLayoutBlock?(make)
            }

            contentView.isHidden = false
            contentView.alpha = 0
            contentView.transform = CGAffineTransform.YP.CreateScale(0)
            animation(.present) {
                contentView.transform = CGAffineTransform.YP.CreateScale(1)
                contentView.alpha = 1
            } completion: {
                completion()
            }
        case .dismiss:
            contentView.alpha = 1
            contentView.transform = CGAffineTransform.YP.CreateScale(1)
            animation(.dismiss) {
                contentView.transform = CGAffineTransform.YP.CreateScale(0.01)
                contentView.alpha = 0
            } completion: {
                contentView.isHidden = true
                completion()
            }
        }
    }

    /// sheet动画
    func sheetAnimtion(_ state: State,
                       sheetConfig: WmcPresentVC.Style.SheetConfig,
                       superView: UIView,
                       contentView: UIView,
                       config: WmcPresentVC.Config,
                       completion: @escaping YPBlock.Empty)
    {
        switch state {
        case .present:
            superView.addSubview(contentView)
            // 先进行动画前的初始布局
            contentView.snp.remakeConstraints { make in
                make.top.equalTo(superView.snp_bottomMargin)
                make.left.right.equalToSuperview()
                if !sheetConfig.isAutoHeight {
                    make.height.equalTo(sheetConfig.startHeight)
                }
            }
            superView.layoutIfNeeded()
            superView.setNeedsUpdateConstraints()
            superView.alpha = 0
            animation(.present) {
                superView.alpha = 1
                // 动画终止布局
                contentView.snp.remakeConstraints { make in
                    config.contentLayoutBlock?(make)
                }
                superView.layoutIfNeeded()
            } completion: {
                completion()
            }
        case .dismiss:
            superView.setNeedsUpdateConstraints()
            superView.alpha = 1
            animation(.dismiss) {
                superView.alpha = 0
                // 先进行动画前的初始布局
                contentView.snp.remakeConstraints { make in
                    make.top.equalTo(superView.snp_bottomMargin)
                    make.left.right.equalToSuperview()
                    if !sheetConfig.isAutoHeight {
                        make.height.equalTo(contentView.frame.height)
                    }
                }
                superView.layoutIfNeeded()
            } completion: {
                completion()
            }
        }
    }

    /// menu动画
    func menuAnimtion(_ state: State,
                      menuConfig: WmcPresentVC.Style.MenuConfig,
                      superView: UIView,
                      contentView: UIView,
                      config: WmcPresentVC.Config,
                      completion: @escaping YPBlock.Empty)
    {
        switch state {
        case .present:
            superView.addSubview(contentView)
            // 进行布局
            contentView.snp.remakeConstraints { make in
                config.contentLayoutBlock?(make)
            }
            // 准备做VC动画
            superView.alpha = 0
            UIView.animate(withDuration: animationDuration.present) {
                superView.alpha = 1
            } completion: { _ in
                completion()
            }

        case .dismiss:
            // 准备做VC动画
            superView.alpha = 1
            UIView.animate(withDuration: animationDuration.dismiss) {
                superView.alpha = 0
            } completion: { _ in
                completion()
            }
        }
    }

    /// notice动画
    func noticeAnimtion(_ state: State,
                        noticeConfig: WmcPresentVC.Style.NoticeConfig,
                        superView: UIView,
                        contentView: UIView,
                        config: WmcPresentVC.Config,
                        completion: @escaping YPBlock.Empty)
    {
        switch state {
        case .present:
            superView.addSubview(contentView)
            // 进行动画前的初始布局
            contentView.snp.remakeConstraints { make in
                make.bottom.equalTo(superView.snp.top)
                make.left.right.equalToSuperview()
                if !noticeConfig.isAutoHeight {
                    make.height.equalTo(noticeConfig.startHeight)
                }
            }
            superView.layoutIfNeeded()
            superView.setNeedsUpdateConstraints()
            // 进行动画
            superView.alpha = 0
            animation(.present) {
                superView.alpha = 1
                // 动画终止布局
                contentView.snp.remakeConstraints { make in
                    config.contentLayoutBlock?(make)
                }
                superView.layoutIfNeeded()
            } completion: {
                completion()
            }
        case .dismiss:
            // 准备做VC动画
            contentView.snp.remakeConstraints { make in
                config.contentLayoutBlock?(make)
            }
            superView.setNeedsUpdateConstraints()
            superView.alpha = 1
            animation(.dismiss) {
                superView.alpha = 0
                // 进行动画前的初始布局
                contentView.snp.remakeConstraints { make in
                    make.bottom.equalTo(superView.snp.top)
                    make.left.right.equalToSuperview()
                    make.height.equalTo(20)
                }
                superView.layoutIfNeeded()
            } completion: {
                completion()
            }
        }
    }

    /// 通用动画函数
    func animation(_ state: State,
                   animateBlock: @escaping YPBlock.Empty,
                   completion: @escaping YPBlock.Empty)
    {
        UIView.animate(withDuration: animationDuration.value(state),
                       delay: delay.value(state),
                       usingSpringWithDamping: usingSpringWithDamping.value(state),
                       initialSpringVelocity: initialSpringVelocity.value(state),
                       options: animationOptions.value(state)) {
            animateBlock()
        } completion: { _ in
            completion()
        }
    }
}

// MARK: - UIViewControllerAnimatedTransitioning

extension WmcPresentAnimation: UIViewControllerAnimatedTransitioning {
    // MARK: - 协议实现

    func transitionDuration(using transitionContext: UIViewControllerContextTransitioning?) -> TimeInterval {
        return animationDuration.value(state)
    }

    func animateTransition(using transitionContext: UIViewControllerContextTransitioning) {
        switch state {
        case .present: presentAnimation(transitionContext)
        case .dismiss: dismissAnimation(transitionContext)
        }
    }

    // MARK: - 动画实现

    // 出现转场
    open func presentAnimation(_ transitionContext: UIViewControllerContextTransitioning) {
        guard let _ = transitionContext.viewController(forKey: .from),
              let toVC = transitionContext.viewController(forKey: .to) as? WmcPresentVC else { return }
        let containerView = transitionContext.containerView

        // 设置配置
        let superView = toVC.view!
        let config = toVC.config
        let contenView = config.contentView

        // 添加进展示视图
        containerView.addSubview(toVC.view)
        toVC.view.frame = Wmc_screen

        // 开始处理内容视图动画
        switch config.style {
        case let .alert(sconfig):
            alertAnimtion(.present, alertConfig: sconfig, superView: superView, contentView: contenView, config: config) {
                transitionContext.completeTransition(true)
            }
        case let .sheet(sconfig):
            sheetAnimtion(.present, sheetConfig: sconfig, superView: superView, contentView: contenView, config: config) {
                transitionContext.completeTransition(true)
            }
        case let .menu(sconfig):
            menuAnimtion(.present, menuConfig: sconfig, superView: superView, contentView: contenView, config: config) {
                transitionContext.completeTransition(true)
            }
        case  .bubble(_):
//            menuAnimtion(.present, menuConfig: sconfig, superView: superView, contentView: contenView, config: config) {
//                transitionContext.completeTransition(true)
//            }
            break
        case let .notice(sconfig):
            noticeAnimtion(.present, noticeConfig: sconfig, superView: superView, contentView: contenView, config: config) {
                transitionContext.completeTransition(true)
            }
        case  .drop(_):
//            menuAnimtion(.present, menuConfig: sconfig, superView: superView, contentView: contenView, config: config) {
//                transitionContext.completeTransition(true)
//            }
            break
        case  .rise(_):
//            menuAnimtion(.present, menuConfig: sconfig, superView: superView, contentView: contenView, config: config) {
//                transitionContext.completeTransition(true)
//            }
            break
        }
    }

    // 消失转场
    open func dismissAnimation(_ transitionContext: UIViewControllerContextTransitioning) {
        guard let fromVC = transitionContext.viewController(forKey: .from) as? WmcPresentVC,
              let _ = transitionContext.viewController(forKey: .to) else { return }
        let _ = transitionContext.containerView

        let superView = fromVC.view!
        let config = fromVC.config
        let contenView = config.contentView

        // 开始处理内容视图动画
        switch config.style {
        case let .alert(sconfig):
            alertAnimtion(.dismiss, alertConfig: sconfig, superView: superView, contentView: contenView, config: config) {
                transitionContext.completeTransition(true)
            }
        case let .sheet(sconfig):
            sheetAnimtion(.dismiss, sheetConfig: sconfig, superView: superView, contentView: contenView, config: config) {
                transitionContext.completeTransition(true)
            }
        case let .menu(sconfig):
            menuAnimtion(.dismiss, menuConfig: sconfig, superView: superView, contentView: contenView, config: config) {
                transitionContext.completeTransition(true)
            }
        case  .bubble(_):
//            menuAnimtion(.dismiss, menuConfig: sconfig, superView: superView, contentView: contenView, config: config) {
//                transitionContext.completeTransition(true)
//            }
            break
        case let .notice(sconfig):
            noticeAnimtion(.dismiss, noticeConfig: sconfig, superView: superView, contentView: contenView, config: config) {
                transitionContext.completeTransition(true)
            }
        case  .drop(_):
//            menuAnimtion(.dismiss, menuConfig: sconfig, superView: superView, contentView: contenView, config: config) {
//                transitionContext.completeTransition(true)
//            }
            break
        case .rise(_):
//            menuAnimtion(.dismiss, menuConfig: sconfig, superView: superView, contentView: contenView, config: config) {
//                transitionContext.completeTransition(true)
//            }
            break
        }
    }
}
